package com.colin.base.deadlock;

import lombok.SneakyThrows;

/**
 * Created by Colin on 2020/3/22 11:10
 * email: colinzhaodong@gmail.com
 * desc: 转账时发生死锁
 *
 * @author zhaod
 */
public class TransferMoney implements Runnable{
	int flag = 1;
	static Account a = new Account(500);
	static Account b = new Account(500);
	static Object lock = new Object();

	public static void main(String[] args) throws InterruptedException {
		TransferMoney r1 = new TransferMoney();
		TransferMoney r2 = new TransferMoney();
		r1.flag = 1;
		r2.flag = 0;
		Thread t1 = new Thread(r1);
		Thread t2 = new Thread(r2);
		t1.start();
		t2.start();
		t1.join();
		t2.join();
		System.out.println("a的余额:"+a.balance);
		System.out.println("b的余额:"+b.balance);
	}
	@SneakyThrows
	@Override
	public void run() {
		if (flag == 1){
			transferMoney(a,b,200);
		}
		if (flag == 0){
			transferMoney(b,a,200);
		}
	}

	public static void transferMoney(Account from, Account to, int amount) {
		class Helper{
			public void transfer(){
					if (from.balance - amount < 0){
						System.out.println("余额不足转账失败");
					}
					from.balance -= amount;
					to.balance += amount;
					System.out.println("成功转账"+amount+"元");
			}
		}
		int fromHash = System.identityHashCode(from);
		int toHash = System.identityHashCode(to);
		if (fromHash > toHash){
			synchronized (from){
				synchronized (to){
					new Helper().transfer();
				}
			}
		}else if (fromHash < toHash){
			synchronized (to){
				synchronized (from){
					new Helper().transfer();
				}
			}
		}else {
			synchronized (lock){
				new Helper().transfer();
			}
		}
//		synchronized (from){
////			try {
////				Thread.sleep(500);
////			} catch (InterruptedException e) {
////				e.printStackTrace();
////			}
//			synchronized (to){
//				if (from.balance - amount < 0){
//					System.out.println("余额不足转账失败");
//				}
//				from.balance -= amount;
//				to.balance += amount;
//				System.out.println("成功转账"+amount+"元");
//			}
//		}
	}

	static class Account{
		int balance;

		public Account(int balance) {
			this.balance = balance;
		}
	}
}
